package com.vip.elastic.service.impl;

import com.vip.common.response.ErrorCode;
import com.vip.common.response.Result;
import com.vip.common.response.Results;
import com.vip.common.util.EmptyUtils;
import com.vip.elastic.dao.ElasticRepository;
import com.vip.elastic.entity.DocumentBean;
import com.vip.elastic.model.dto.AddDocumentDto;
import com.vip.elastic.service.IDocumentBeanService;
import com.vip.elastic.service.IIndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * DocumentBean Service
 *
 * @author wgb
 * @date 2020/11/10 10:52
 */
@Slf4j
@Service
public class DocumentBeanServiceImpl implements IDocumentBeanService {

    @Autowired
    private ElasticRepository elasticRepository;

    @Override
    public Result<String> save(AddDocumentDto dto) {
        try {
            DocumentBean documentBean = new DocumentBean();
            BeanUtils.copyProperties(dto, documentBean);
            elasticRepository.save(documentBean);
            return Results.newSuccessResult(null, "保存成功");
        } catch (Exception e) {
            log.error("Document保存出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "保存失败");
    }

    @Override
    public Result<String> saveMultiDoc(List<AddDocumentDto> list) {
        try {
            List<DocumentBean> docList = list.stream().map(x -> {
                DocumentBean doc = new DocumentBean();
                BeanUtils.copyProperties(x, doc);
                return doc;
            }).collect(Collectors.toList());
            elasticRepository.saveAll(docList);
            return Results.newSuccessResult(null, "保存成功");
        } catch (Exception e) {
            log.error("Document批量保存出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "保存失败");

    }

    @Override
    public Result<Iterator<DocumentBean>> findAll() {
        try {
            Iterator<DocumentBean> result = elasticRepository.findAll().iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询全部出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<List<DocumentBean>> getList(Integer pageNo, Integer pageSize, String content, String firstCode, String secondCode, Integer type) {
        try {
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            if (!EmptyUtils.basicIsEmpty(content)) {
                queryBuilder.should(QueryBuilders.matchQuery("content", content));
            }
            if (!EmptyUtils.basicIsEmpty(firstCode)) {
                queryBuilder.should(QueryBuilders.matchQuery("firstCode", firstCode));
            }
            if (!EmptyUtils.basicIsEmpty(secondCode)) {
                queryBuilder.should(QueryBuilders.matchQuery("secondCode", secondCode));
            }
            if (!EmptyUtils.basicIsEmpty(type)) {
                queryBuilder.should(QueryBuilders.matchQuery("type", type));
            }
            //设置排序
            FieldSortBuilder sort = SortBuilders.fieldSort("id").order(SortOrder.DESC);
            //设置分页
            Pageable pageable = PageRequest.of((pageNo - 1) * pageSize, pageSize);
            SearchQuery searchQuery = new NativeSearchQueryBuilder()
                    .withPageable(pageable)
                    .withQuery(queryBuilder)
                    .withSort(sort)
                    .build();
            log.info("searchLogPage: searchContent [{}] \n DSL  = \n {}", content, searchQuery.getQuery().toString());
            Page<DocumentBean> areaPage = elasticRepository.search(searchQuery);
            return Results.newSuccessResult(areaPage.getContent(), "查询成功", areaPage.getTotalElements());
        } catch (Exception e) {
            log.error("Document分页查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> matchQuery(String field, String value) {
        try {
            Iterator<DocumentBean> result = elasticRepository.search(QueryBuilders.matchQuery(field, value)).iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询指定字段分词查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> commonTermsQuery(String field, String value) {
        try {
            Iterator<DocumentBean> result = elasticRepository.search(QueryBuilders.commonTermsQuery(field, value)).iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询指定字段分词查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> multiMatchQuery(String value, String... fields) {
        try {
            Iterator<DocumentBean> result = elasticRepository.search(QueryBuilders.multiMatchQuery(value, fields)).iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询多个字段分词查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> matchPhraseQuery(String field, String value) {
        try {
            Iterator<DocumentBean> result = elasticRepository.search(QueryBuilders.matchPhraseQuery(field, value)).iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询多个字段分词查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> matchPhrasePrefix(String field, String value) {
        try {
            Iterator<DocumentBean> result = elasticRepository.search(QueryBuilders.matchPhrasePrefixQuery(field, value)).iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询多个字段分词查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> disMaxQuery(String field, String value) {
        try {
            Iterator<DocumentBean> result = elasticRepository.search(QueryBuilders.disMaxQuery().add(
                    QueryBuilders.matchPhrasePrefixQuery(field, value)).add(QueryBuilders.matchPhraseQuery(field, value))).iterator();
            return Results.newSuccessResult(result, "查询成功");
        } catch (Exception e) {
            log.error("Document查询多个字段分词查询出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public Result<Iterator<DocumentBean>> idsQuery(List<Long> ids) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> termQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> fuzzyQuery(String field, String value, Integer fuzzy) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> prefixQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> rangeQuery(String field, String gte, String lte) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> wildcardQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> regexpQuery(String field, String regexp) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> queryStringQuery(List<String> fields, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> simpleQueryStringQuery(List<String> fields, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> boostingQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> boolQuery(Map<String, List<String>> params) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanTermQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanFirstQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanNearQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanNotQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanOrQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanWithinQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanContainingQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> spanMultiTermQueryBuilder(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> fieldMaskingSpanQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> constantScoreQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> functionScoreQueryNoFunction(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> functionScoreQuery(List<String> values) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> moreLikeThisQuery(List<String> values) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> nestedQuery(String field, String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> termsQuery(String fields, List<String> value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> wrapperQuery(String value) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> typeQuery(String type) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> termsLookupQuery(String index, String type, String id, String field) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> scriptQuery(String value, String source) {
        return null;
    }

    @Override
    public Result<Iterator<DocumentBean>> existsQuery(String field) {
        return null;
    }
}
